import { antennaInfo, AntennaType } from './data';
import {
  getQueryParam,
  httpApi,
  MessageTip,
  QueryParamKeys,
  FeatureManager,
  PickLine,
} from '@amcax/base';
import { wsApi } from '@app-base/server';
import { docMgr } from '@app-base/module';
import { Vector3, Vector3Tuple } from 'three';
import { ctx2, userEvents } from '@app-base/module';
import { loadEmit, MODEL_REMOVE_ADD } from '@app-base/common/events/CoreEvent';
import {
  createCrossByEdges,
  createCrossByPointArray,
  isSameLocation,
} from '../cmd-elec-box';
import { CSText } from './CSText';
const arrowGroup = [];
let timer = null;
let count = 0;
let timer2 = null;
let timer3 = null;

const setCurrentBoxByName = async (name: string = '零件几何体.1') => {
  if (!FeatureManager.isFeatureEnabled('set-current-box')) {
    return;
  }
  const parent = docMgr.documentObjects.filter(
    (item) =>
      item.type === 'GeomBox' &&
      item.label.startsWith(name + (name === '零件几何体.1' ? '' : '点设置')),
  );
  if (!parent || parent.length <= 0) {
    const res = await wsApi.execCmd({
      c: 'CreateGeomBox',
      name: name + (name === '零件几何体.1' ? '' : '点设置'),
    });
    if (res?.id) {
      await wsApi.execCmd({
        c: 'SetCurrentBox',
        o: res.id,
      });
      docMgr.workingObjectDxid = res.id;
    }
  } else {
    await wsApi.execCmd({
      c: 'SetCurrentBox',
      o: parent[0].dxid,
    });
    docMgr.workingObjectDxid = parent[0].dxid;
  }
};

const setCurrentBox = async (id: string) => {
  if (!FeatureManager.isFeatureEnabled('set-current-box')) {
    return;
  }
  const parent = docMgr.documentObjects.filter(
    (item) =>
      item.type === 'GeomBox' &&
      item?.children?.length > 0 &&
      item?.children?.find((e) => e.dxid === id),
  );
  if (parent && parent.length > 0) {
    await wsApi.execCmd({
      c: 'SetCurrentBox',
      o: parent[0].dxid,
    });
    docMgr.workingObjectDxid = parent[0].dxid;
  }
};

const createArrow = (
  direction: Vector3,
  midPoint: Vector3,
  color: number,
  tag: string,
) => {
  const offset = 15;
  const vector = direction.clone();

  const arrow = new PickLine({
    vertexs: [new Vector3(), vector.clone().setLength(offset)],
    showArrow: true,
    isKeepSize: true,
    keepSizeOrigin: midPoint.clone().toArray(),
    camera: ctx2.viewer.sceneSetup.oCamera,
    lineWidth: 4,
  });

  arrow.setColor(color);
  arrow?.arrow?.setColor(color);
  arrow.addTo(ctx2.cadScene.toolsGroup);

  const textPosition = midPoint.clone().toArray();
  const text = new CSText({
    size: 2,
    text: tag,
    color: color,
    direction: vector.toArray(),
    needKeepSize: true,
    translate: vector
      .clone()
      .setLength(offset + 2)
      .toArray(),
    position: textPosition,
    camera: ctx2.viewer.sceneSetup.oCamera,
  });
  text.addTo(ctx2.cadScene.toolsGroup);
  ctx2.viewer.requestRender();

  return { arrow, text };
};

export const elecModelImport = async (antennas) => {
  loadEmit(true);
  ctx2.viewer.fitObjectView(500);
  userEvents.on(MODEL_REMOVE_ADD, modelCompound);
  const temp = isJSON(antennas) ? JSON.parse(antennas) : antennas;
  for (const antenna of temp.cadModels) {
    await doRender(antenna.path, antenna);
  }
  timer3 = setTimeout(() => {
    ctx2.viewer.fitObjectView();
    timer3 && clearTimeout(timer3);
  }, 1000);
  // 检测模型天线是否合并完成
  timer2 = setInterval(() => {
    if (count <= 0) {
      timer2 && clearInterval(timer2);
      setModelPosition(temp.cadModels);
    }
  }, 100);
};
export const elecImportFreePoints = async (freePoints) => {
  const temp = isJSON(freePoints) ? JSON.parse(freePoints) : freePoints;
  for (const element of temp || []) {
    if (element?.point) {
      const from = element?.from ? element.from : '零件几何体.1';
      await setCurrentBoxByName(from);
      const res = await wsApi.createPoint(element.point);
      if (res?.id && element?.name) {
        await wsApi.setLabel(
          res.id,
          (from === '零件几何体.1' ? '' : from + '-') + element.name,
        );
      }
    }
  }
};
export const elecDeleteFreePoints = async (freePoints) => {
  const temp = isJSON(freePoints) ? JSON.parse(freePoints) : freePoints;
  temp?.forEach((element) => {
    element.id && wsApi.delete(element.id);
  });
};
export const elecImportBox = async (box) => {
  const temp = isJSON(box) ? JSON.parse(box) : box;
  temp?.forEach(async (element) => {
    if (element.params) {
      wsApi.createPrimitiveNew('Box', element.params);
      const { nx, ny, nz } = element.params;
      const pointXYZ = { x: [], y: [], z: [] };
      element.edges
        ?.filter(
          (item) =>
            isSameLocation(item.mesh[0], element.params.origin) ||
            isSameLocation(item.mesh[1], element.params.origin),
        )
        ?.forEach((item) => {
          const { positions, dir } = createCrossByEdges(
            item.mesh[0],
            item.mesh[1],
            { nx, ny, nz },
          );
          pointXYZ[dir] = positions;
        });
      createCrossByPointArray(pointXYZ.x, pointXYZ.y, pointXYZ.z);
    }
  });
};
export const elecImportIncident = async (incident) => {
  const data = isJSON(incident) ? JSON.parse(incident) : incident;
  const { thetaDeg, phiDeg, polarDeg, posX, posY, posZ } = data;
  const theta = (thetaDeg * Math.PI) / 180;
  const phi = (phiDeg * Math.PI) / 180;
  const polar = (polarDeg * Math.PI) / 180;
  const midPoint = new Vector3(posX, posY, posZ);

  const propagationDirection = new Vector3(
    Math.sin(theta) * Math.cos(phi),
    Math.sin(theta) * Math.sin(phi),
    Math.cos(theta),
  );
  propagationDirection.normalize();
  const { arrow: propagationArrow, text: propagationText } = createArrow(
    propagationDirection,
    midPoint,
    0xff0000,
    'S',
  );
  arrowGroup.push({ arrow: propagationArrow, text: propagationText });

  const polarizationDirection = new Vector3(
    Math.cos(polar) * Math.cos(theta) * Math.cos(phi) +
      Math.sin(polar) * Math.sin(phi),
    Math.cos(polar) * Math.cos(theta) * Math.sin(phi) -
      Math.sin(polar) * Math.cos(phi),
    -(Math.cos(polar) * Math.sin(theta)),
  );
  polarizationDirection.normalize();
  const { arrow: polarizationArrow, text: polarizationText } = createArrow(
    polarizationDirection,
    midPoint,
    0x00ff00,
    'E',
  );
  arrowGroup.push({ arrow: polarizationArrow, text: polarizationText });
};
export const elecClearIncident = () => {
  arrowGroup.forEach((item) => {
    ctx2.cadScene.toolsGroup.remove(item?.arrow);
    ctx2.cadScene.toolsGroup.remove(item?.text);
    item?.arrow?.destroy();
    item?.text?.destroy();
  });
  arrowGroup.length = 0;
  ctx2.viewer.requestRender();
};

function modelCompound() {
  count = count - 1;
}
export const doRender = async (filepath: string, antenna: AntennaType) => {
  const params = {
    t: filepath,
  };
  try {
    const res = await wsApi.importModel(params);
    let dxid = res?.added[0];
    antenna.type === 'plane' && (antennaInfo().PlaneId = dxid);
    if (antenna.type === 'antenna') {
      // todo: 临时延迟，后续需要判断模型完全渲染完了再执行
      await new Promise((resolve) => setTimeout(resolve, 1000));
      count = count + 1;
      // 合并模型
      await setCurrentBox(dxid);
      const compoundRes = await wsApi.createCompound(res?.added);
      antenna.dxid = dxid = compoundRes.id;
      // todo: 临时延迟，确保合并后后续再移动模型
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
    try {
      await wsApi.setLabel(dxid, antenna.name);
    } catch (e) {
      console.error('elecModelImport', e);
      antennaInfo().setIdAndLabelNameMap(dxid, antenna.name);
    }
  } catch (e: any) {
    MessageTip.error(e.message);
    loadEmit(false);
  }
};
async function setModelPosition(antennas: AntennaType[]) {
  for (const antenna of antennas) {
    if (antenna.type === 'antenna') {
      const temp = antennaInfo().getAntennaInfoById(antenna.dxid).args;
      if (!temp || !antenna.args) {
        continue;
      }
      const { x, y, z, sx, sy, sz, ox, oy, oz } = antenna.args;
      if (temp.x !== x || temp.y !== y || temp.z !== z) {
        const end: Vector3Tuple = [x, y, z];
        const start: Vector3Tuple =
          sx == undefined || sx == null ? [0, 0, 0] : [sx, sy, sz];
        const origin: Vector3Tuple =
          ox == undefined || ox == null
            ? [start[0], start[1], start[2]]
            : [ox, oy, oz];
        console.log('temp', temp, 'start', start, 'origin', origin);
        if (temp.dxid) {
          await setCurrentBox(temp.dxid);
          await translation(temp.dxid, end, start, origin);
        }
      }
    }
  }
  // 检测模型天线是否平移完成
  timer = setInterval(() => {
    if (antennaInfo().getHandlersNum() <= 0) {
      timer && clearInterval(timer);
      antennaInfo().init();
      setRotation(antennas);
    }
  }, 100);

  if (window && window['miopBrowser'] && window['miopBrowser']['call']) {
    window['miopBrowser']?.call({ method: 'loadCompleted' });
  }
}
async function translation(dxid, end, start, origin) {
  await wsApi.translation({
    id: dxid,
    start,
    end,
    origin,
  });
  await new Promise((resolve) => setTimeout(resolve, 500));
  antennaInfo().setHandlersNum();
}
async function setRotation(antennas) {
  let indx = 0;
  for (const antenna of antennas) {
    if (antenna.args) {
      indx = indx + 1;
      const temp = antennaInfo().getAntennaInfoById(antenna.dxid).args;
      const { x, y, z } = antenna.args;
      const end: Vector3Tuple = [x, y, z];
      const { phi, theta } = antenna.args;
      if (temp.dxid && (phi !== temp.phi || theta != temp.theta)) {
        await setCurrentBox(temp.dxid);
        await setModelRotation(phi, theta, end, temp.dxid);
      }
    }
  }
  // antennaInfo().setVisable();
}
const yAxis = [0, 1, 0];
const zAxis = [0, 0, 1];
async function setModelRotation(phi, theta, origin, id) {
  const params = {
    mode: 'twoAxis',
    axis: [origin, yAxis],
    angle: theta,
    axis2: [origin, zAxis],
    angle2: phi,
    keepSrc: false,
  };
  await wsApi.create3dRotate(id, params);
}
export function elecPointList() {
  return antennaInfo().exportPointJson();
}
export function elecFreePoints() {
  return antennaInfo().exportFreePointJson();
}
export function elecBox() {
  return antennaInfo().exportElecBoxJson();
}
export function elecModelDeleteByName(data) {
  const temp = isJSON(data) ? JSON.parse(data) : data;
  const parent = docMgr.documentObjects.filter(
    (item) => item.type === 'GeomBox' && item.label === temp?.name,
  );
  if (parent && parent.length > 0) {
    return wsApi.delete(parent[0].dxid);
  }
  return false;
}
export function elecSetWireOrPath(data) {
  const temp = isJSON(data) ? JSON.parse(data) : data;
  localStorage.setItem('elecWireNames', JSON.stringify(temp?.names ?? []));
  localStorage.setItem('elecWireOptions', JSON.stringify(temp?.options ?? []));
}
const documentId = getQueryParam<string>(QueryParamKeys.DOCUMENT_ID);
export async function elecModelExport() {
  const { data } = await httpApi.getExportPath(documentId, 'step');
  const params = {
    t: data.path,
    o: [],
    lod: 0.01,
    mode: 'full',
  };
  await wsApi.exportModel(params);
  return data?.dl || '';
}

export async function elecModelExportLocal(data) {
  const temp = isJSON(data) ? JSON.parse(data) : data;
  const params = {
    t: temp.path,
    o: [],
    lod: 0.01,
    mode: 'full',
  };
  await wsApi.exportModel(params);
  return temp.path;
}

function isJSON(str) {
  if (typeof str == 'string') {
    try {
      JSON.parse(str);
      return true;
    } catch (e) {
      console.error('isJSON', e);
      return false;
    }
  }
  console.error('It is not a string!');
  return false;
}
